/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "local_net_communication.h"
#include "local_net_def.h"
#include "local_net_udp.h"
#include "local_net_utils.h"

#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <cJSON.h>
#include <math.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>

#ifdef L2_DEVICE
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#endif

#define DISC_PORT 50000
#define BC_SLEEP_TIME 5
#define EXEC_SUCC 0
#define EXEC_FAILED -1
#define BROADCAST_ARRSIZE 1024

#define MSG_SZ 1024

// 解析的类型
const char *BROADCAST = "broadcast";
const char *UNICAST = "command";
const char *RESPONSE = "response";

typedef struct {
    char deviceId[DEVICE_ID_LEN];
    uint16_t dataLen;
    char data[MSG_SZ];
#ifdef L2_DEVICE
    long dataType;
#endif
} LocalNetMsgRecv;

typedef struct {
    uint8_t msgId;
    char deviceId[DEVICE_ID_LEN];
} LocalNetMsgRespData;

typedef struct {
    char subscribe[32];
    char group[32];
} DestDevIdCheckData;

typedef struct {
    void *next;
    char destDevId[DEVICE_ID_LEN];
} DeviceIdHang;

typedef struct {
    char *msg;
    uint8_t sendCnt;
    uint8_t msgId;
    struct timeval time;
    char publish[32];
    DeviceIdHang *pDestDevId;
} LocalNetMsgSendNode;

typedef struct {
    uint8_t msgIdCnt;
    Node_t *list;
#ifdef L0_DEVICE
    osMutexId_t listMutex;
#elif defined(L2_DEVICE)
    pthread_mutex_t listMutex;
#endif
} LocalNetMsgSendList;
typedef LocalNetMsgSendList *MsgSendListHandle;

typedef int8_t (*LocalNetRecvCb)(const char *msg);

typedef int8_t (*LocalNetDevListNoticeCb)(Node_t *devList);

typedef struct {
    LocalNetThreadStatus recvMsgDealThreadStatus;
    LocalNetThreadStatus devOfflineJudgeThreadStatus;
    LocalNetThreadStatus sendMsgDealThreadStatus;
    MsgSendListHandle sendReadyMsgList;      // 待发送信息列表
    Node_t *onlineDevList;                   // 在线设备列表
    LocalNetRecvCb recvCb;                   // 数据接收回调
    LocalNetDevListNoticeCb devListNoticeCb; // 在线设备变化通知回调
#ifdef L0_DEVICE
    osThreadId_t recvMsgDealThread;      // 数据接收处理线程
    osMessageQueueId_t recvMsgDealQueue; // 数据接收处理消息队列
    osThreadId_t devOfflineJudgeThread;  // 设备在线判断线程
    osThreadId_t sendMsgDealThread;      // 消息发送线程
#elif defined(L2_DEVICE)
    pthread_t recvMsgDealThread;     // 数据接收处理线程
    key_t key;                       // 消息队列msgid所对应的key
    int recvMsgDealQueue;            // 数据接收处理消息队列
    pthread_t devOfflineJudgeThread; // 设备在线判断线程
    pthread_t sendMsgDealThread;     // 消息发送线程
#endif
} LocalNetCommController;

static LocalNetCommController g_localNetCommCtl;

static MsgSendListHandle LocalNetMsgSendListInit(void)
{
    MsgSendListHandle msgSendList = (MsgSendListHandle)malloc(sizeof(LocalNetMsgSendList));
    if (!msgSendList) {
        LOG_E("malloc msg send list handle failed!");
        return NULL;
    }
    msgSendList->list = CreateDlist();
    if (!(msgSendList->list)) {
        LOG_E("create ipd list failed!");
        goto MSG_SEND_LIST_INIT_ERR;
    }

#ifdef L0_DEVICE
    msgSendList->listMutex = osMutexNew(NULL);
    if (!(msgSendList->listMutex)) {
        LOG_E("create ipd list mutex failed!");
        goto MSG_SEND_LIST_INIT_ERR;
    }
#elif defined(L2_DEVICE)
    pthread_mutex_init(&(msgSendList->listMutex), NULL);
#endif

    msgSendList->msgIdCnt = 1;
    return msgSendList;
MSG_SEND_LIST_INIT_ERR:
    if (msgSendList) {
        free(msgSendList);
        msgSendList = NULL;
    }
    return NULL;
}

static void LocalNetmsgSendListDeinit(MsgSendListHandle msgSendList)
{
    DestroyDlist(&(msgSendList->list));

#ifdef L0_DEVICE
    osMutexDelete(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_destroy(&(msgSendList->listMutex));
#endif

    return;
}

static int8_t LocalNetMsgSendListNodeAdd(const MsgSendListHandle msgSendList, LocalNetMsgSendNode *pMsgSendNode)
{
    int8_t ret = -1;

    LOG_I("Add new msg send Node data to list!");
    pMsgSendNode->msgId = msgSendList->msgIdCnt;
    pMsgSendNode->sendCnt = 5;
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif

    if (!InsertHdlist(msgSendList->list, pMsgSendNode, sizeof(LocalNetMsgSendNode))) { // 插入头部
        LOG_I("InsertHdlist success!");
        ret = 0;
    } else {
        LOG_E("InsertHdlist failed!");
    }
    msgSendList->msgIdCnt++;
    if (0 == msgSendList->msgIdCnt) {
        msgSendList->msgIdCnt = 1;
    }
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif

    return ret;
}

static int cmpStrFun(const void *data1, const void *data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    const char *str1 = (const char *)data1;
    const char *str2 = (const char *)data2;
    return strcmp(str1, str2);
}

static int MsgIdCmp(const void *data1, const void *data2)
{
    int ret = -1;

    if (!data1 || !data2) {
        LOG_E("data1 or data2 is NULL!");
        return ret;
    }

    const uint8_t msgId = *(const uint8_t *)data1;
    const LocalNetMsgSendNode *srcMsgSendNode = (const LocalNetMsgSendNode *)data2;

    if (msgId == srcMsgSendNode->msgId) {
        ret = 0;
    }
    return ret;
}

static int DestDevIdCheckDataCmp(const void *data1, const void *data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    int ret = -1;
    const DestDevIdCheckData *DestDevIdCheckData = (const char *)data1;
    const NetBroadcastPara_t *para2 = (const NetBroadcastPara_t *)data2;

    LOG_I("DestDevIdCheckDataCmp[%s]!", DestDevIdCheckData->subscribe);
    if (FindVdlist(para2->subscribe, DestDevIdCheckData->subscribe, cmpStrFun)) {
        LOG_I("Find the subscribe[%s] on the list!", DestDevIdCheckData->subscribe);
        if ((0 == strncmp(DestDevIdCheckData->group, para2->group, 32)) ||
            (0 == strncmp(para2->group, "all", strlen("all") + 1))) {
            LOG_I("destDev group %s", para2->group);
            ret = 0;
        }
    }
    return ret;
}

static int PublishCmp(const void *data1, const void *data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    int ret = -1;
    const char *pPublish = data1;
    const NetBroadcastPara_t *para2 = (const NetBroadcastPara_t *)data2;

    if (FindVdlist(para2->publish, pPublish, cmpStrFun)) {
        LOG_I("Find the pPublish[%s] on the list!", pPublish);
        ret = 0;
    }
    return ret;
}

static int TimeofDayCmp(const void *data1, const void *data2)
{
    const LocalNetMsgSendNode *para1 = (const LocalNetMsgSendNode *)data1;
    const LocalNetMsgSendNode *para2 = (const LocalNetMsgSendNode *)data2;

    return (para2->time.tv_sec - para1->time.tv_sec);
}

static int8_t LocalNetMsgSendListNodeDelete(const MsgSendListHandle msgSendList, uint8_t msgId)
{
    int8_t ret = -1;
    DeviceIdHang *pDeviceIdHang;
    DeviceIdHang *pDeviceIdHangNxt;
    LocalNetMsgSendNode *pMsgSendNode;
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif

    Node_t *node = FindVdlist(msgSendList->list, &msgId, MsgIdCmp); //按值查找
    if (!node) {                                                    // 不存在该MsgId的成员
        LOG_I("can not find member with this MsgId from the list!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    pMsgSendNode = (LocalNetMsgSendNode *)(node->data);
    if (!pMsgSendNode) {
        LOG_E("the node data is null!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    pDeviceIdHang = pMsgSendNode->pDestDevId;
    if (!pDeviceIdHang) {
        LOG_E("the destination deviceId is null!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    while (pDeviceIdHang) {
        pDeviceIdHangNxt = pDeviceIdHang->next;
        free(pDeviceIdHang);
        pDeviceIdHang = pDeviceIdHangNxt;
    }
    free(pMsgSendNode->msg);
    pMsgSendNode->msg = NULL;
    DeleteVdlist(msgSendList->list, &msgId, MsgIdCmp); //按值删除
    ret = 0;

MSG_SEND_LIST_DELETE_NODE_END:
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif

    return ret;
}

static int SendListPublishCmp(const void *data1, const void *data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    const char *pPublish = data1;
    const LocalNetMsgSendNode *para2 = (const LocalNetMsgSendNode *)data2;

    return strcmp(pPublish, para2->publish);
}

static void LocalNetMsgSendListNodeDeleteByPublish(const MsgSendListHandle msgSendList, const char *publish)
{
    DeviceIdHang *pDeviceIdHang;
    DeviceIdHang *pDeviceIdHangNxt;
    LocalNetMsgSendNode *pMsgSendNode;
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif

    Node_t *node = FindVdlist(msgSendList->list, publish, SendListPublishCmp); //按值查找
    if (!node) {                                                               // 不存在该publish的成员
        LOG_I("can not find member with this MsgId from the list!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    pMsgSendNode = (LocalNetMsgSendNode *)(node->data);
    if (!pMsgSendNode) {
        LOG_E("the node data is null!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    pDeviceIdHang = pMsgSendNode->pDestDevId;
    if (!pDeviceIdHang) {
        LOG_E("the destination deviceId is null!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    while (pDeviceIdHang) {
        pDeviceIdHangNxt = pDeviceIdHang->next;
        free(pDeviceIdHang);
        pDeviceIdHang = pDeviceIdHangNxt;
    }
    free(pMsgSendNode->msg);
    pMsgSendNode->msg = NULL;
    DeleteVdlist(msgSendList->list, publish, SendListPublishCmp); //按值删除
    LOG_I("delete %s type msg node!", publish);

MSG_SEND_LIST_DELETE_NODE_END:
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif
}

static int8_t LocalNetMsgSendListDeletebyResp(const MsgSendListHandle msgSendList,
                                              const LocalNetMsgRespData *pMsgRespData)
{
    int8_t ret = -1;
    DeviceIdHang *pDeviceIdHang;
    DeviceIdHang *pDeviceIdHangPre;
    LocalNetMsgSendNode msgSendNode;
    LocalNetMsgSendNode *pMsgSendNode;

    memset(&msgSendNode, 0, sizeof(LocalNetMsgSendNode));
    msgSendNode.msgId = pMsgRespData->msgId;

#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif

    Node_t *node = FindVdlist(msgSendList->list, &(pMsgRespData->msgId), MsgIdCmp); //按值查找
    if (!node) {                                                                    // 不存在该MsgId的成员
        LOG_I("can not find member with this MsgId from the list!");
        goto MSG_SEND_LIST_DELETE_DEST_END;
    }

    pMsgSendNode = (LocalNetMsgSendNode *)(node->data);
    if ((NULL == pMsgSendNode) || (NULL == pMsgSendNode->pDestDevId)) {
        LOG_E("pMsgSendNode or pMsgSendNode->pDestDevId is null");
        goto MSG_SEND_LIST_DELETE_DEST_END;
    }

    if (!(pMsgSendNode->pDestDevId->next)) { // 该待发送消息中，仅有一个目标设备Id
        LOG_I("local save DevId %s", pMsgSendNode->pDestDevId->destDevId);
        LOG_I("resp DevId %s", pMsgRespData->deviceId);
        if (strncmp(pMsgSendNode->pDestDevId->destDevId, pMsgRespData->deviceId, DEVICE_ID_LEN)) {
            LOG_E("can not find destDeviceId from the member!");
            goto MSG_SEND_LIST_DELETE_DEST_END;
        }
        LOG_I("This msg all destination have responsed, will be destroy!");
        // 释放资源
        free(pMsgSendNode->pDestDevId);
        pMsgSendNode->pDestDevId = NULL;
        free(pMsgSendNode->msg);
        pMsgSendNode->msg = NULL;
        DeleteVdlist(msgSendList->list, &(pMsgRespData->msgId), MsgIdCmp); //按值删除
        ret = 0;
    } else { // 该待发送消息中，有一个以上目标设备Id
        LOG_I("msgList include multiple msg, choose one correct to delete!");
        pDeviceIdHang = pMsgSendNode->pDestDevId;
        if (!strncmp(pDeviceIdHang->destDevId, pMsgRespData->deviceId,
                     DEVICE_ID_LEN)) { // 收到的是第一个目标设备Id的回复
            // 目标设备解链
            pMsgSendNode->pDestDevId = pDeviceIdHang->next;
            // 释放资源
            free(pDeviceIdHang);
            pDeviceIdHang = NULL;
            ret = 0;
            goto MSG_SEND_LIST_DELETE_DEST_END;
        }
        while (pDeviceIdHang) {
            pDeviceIdHangPre = pDeviceIdHang;
            pDeviceIdHang = pDeviceIdHang->next;
            if (!strncmp(pDeviceIdHang->destDevId, pMsgRespData->deviceId, DEVICE_ID_LEN)) {
                // 目标设备解链
                pDeviceIdHangPre->next = pDeviceIdHang->next;
                // 释放资源
                free(pDeviceIdHang);
                pDeviceIdHang = NULL;
                ret = 0;
                goto MSG_SEND_LIST_DELETE_DEST_END;
            }
        }
        LOG_E("can not find destDeviceId from the member!");
    }
MSG_SEND_LIST_DELETE_DEST_END:
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif

    return ret;
}

static LocalNetMsgSendNode *LocalNetMsgSendListNodeGet(const MsgSendListHandle msgSendList)
{
    if (!msgSendList || !(msgSendList->list) || !(msgSendList->list->after)) {
        LOG_E("msgSendList is null or empty!");
        return NULL;
    }
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif
    // 按照时间顺序排序
    SelectSortdlist(msgSendList->list, TimeofDayCmp);
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif

    return (LocalNetMsgSendNode *)(msgSendList->list->after->data);
}

int8_t LocalNetMsgRecvCbReg(int8_t (*recvCb)(const char *msg))
{
    g_localNetCommCtl.recvCb = recvCb;
    return 0;
}

int8_t LocalNetDevListNoticeCbReg(int8_t (*devListNoticeCb)(Node_t *devList))
{
    g_localNetCommCtl.devListNoticeCb = devListNoticeCb;
    return 0;
}

static int8_t responseMsgPrase(const cJSON *respJson, ResponsePara_t *resp)
{
    cJSON *tempValue = NULL;

    if (respJson == NULL || resp == NULL) {
        LOG_E("NULL POINT! \n");
        return -1;
    }

    tempValue = cJSON_GetObjectItem(respJson, "id");
    if (!tempValue) {
        LOG_E("resp msg id is null!");
        return -1;
    }
    LOG_I("parse resp DevId %s", tempValue->valuestring);
    strcpy(resp->id, tempValue->valuestring);

    tempValue = cJSON_GetObjectItem(respJson, "result");
    if (!tempValue) {
        LOG_E("resp msg result is null!");
        return -1;
    }
    strcpy(resp->result, tempValue->valuestring);

    tempValue = cJSON_GetObjectItem(respJson, "state");
    if (!tempValue) {
        LOG_E("resp msg state is null!");
        return -1;
    }
    resp->state = (enum ResponseState)tempValue->valueint;

    return 0;
}

static int8_t groupCheck(char *group)
{
    if ((NULL == group) || (NULL == g_localNetCommCtl.onlineDevList) ||
        (NULL == g_localNetCommCtl.onlineDevList->after) || (NULL == g_localNetCommCtl.onlineDevList->after->data)) {
        LOG_E("selfDevInfo or boardcast group data is null!");
        return -1;
    }
    NetBroadcastPara_t *pSelfDevInfo = (NetBroadcastPara_t *)(g_localNetCommCtl.onlineDevList->after->data);

    // 两设备为同一个group
    if (0 == strncmp(pSelfDevInfo->group, group, strlen(pSelfDevInfo->group))) {
        return 0;
    }
    // 设备自身为L2
    if (0 == strncmp(pSelfDevInfo->group, "all", strlen("all"))) {
        return 0;
    }
    // 对方设备为L2
    if (0 == strncmp(group, "all", strlen("all"))) {
        return 0;
    }

    LOG_E("dev is not at same group!");
    return -1;
}

static int8_t boardcastMsgParse(const char *msg, NetBroadcastPara_t *broadcast)
{
    if (!msg || !broadcast) {
        LOG_E("NULL POINT!\n");
        return -1;
    }
    cJSON *tempValue = NULL;
    cJSON *broadJson = cJSON_Parse(msg);
    if (!broadJson) {
        LOG_E("cJSON_Parse %s failed!", msg);
        return -1;
    }
    cJSON *deviceJson = cJSON_GetObjectItem(broadJson, "device");
    if (!deviceJson) {
        goto BROADCAST_PARSE_ERR;
    }
    tempValue = cJSON_GetObjectItem(deviceJson, "id");
    if (tempValue) {
        strncpy(broadcast->id, tempValue->valuestring, DEVICE_ID_LEN);
        // LOG_I("deviceId: [%s]", tempValue->valuestring);
    }

    tempValue = cJSON_GetObjectItem(deviceJson, "name");
    if (tempValue) {
        strncpy(broadcast->name, tempValue->valuestring, strlen(tempValue->valuestring) + 1);
        // LOG_I("name: [%s]", tempValue->valuestring);
    }

    tempValue = cJSON_GetObjectItem(deviceJson, "type");
    if (tempValue) {
        strncpy(broadcast->type, tempValue->valuestring, strlen(tempValue->valuestring) + 1);
        // LOG_I("type: [%s]", tempValue->valuestring);
    }

    tempValue = cJSON_GetObjectItem(deviceJson, "group");
    if (tempValue) {
        if (0 != groupCheck(tempValue->valuestring)) {
            goto BROADCAST_PARSE_ERR;
        }
        strncpy(broadcast->group, tempValue->valuestring, strlen(tempValue->valuestring) + 1);
        // LOG_I("group: [%s]", tempValue->valuestring);
    }

    tempValue = cJSON_GetObjectItem(deviceJson, "priority");
    if (tempValue) {
        broadcast->priority = tempValue->valueint;
        // LOG_I("priority: [%d]", tempValue->valueint);
    }
    // parse subscribe []
    broadcast->subscribe = CreateDlist();
    tempValue = cJSON_GetObjectItem(broadJson, "subscribe");
    if (!broadcast->subscribe || !tempValue) {
        goto BROADCAST_PARSE_ERR;
    }
    int tempArrSize = cJSON_GetArraySize(tempValue);
    // LOG_I("subscribe num: [%d]", tempArrSize);
    if (tempArrSize > 0) {
        cJSON *jsonArrItem = NULL;
        for (int i = 0; i < tempArrSize; i++) {
            jsonArrItem = cJSON_GetArrayItem(tempValue, i);
            if (jsonArrItem) {
                InsertTdlist(broadcast->subscribe, jsonArrItem->valuestring, strlen(jsonArrItem->valuestring) + 1);
                // LOG_I("subscribe[%d]: [%s]", i, jsonArrItem->valuestring);
            }
        }
    }

    // parse publish []
    broadcast->publish = CreateDlist();
    tempValue = cJSON_GetObjectItem(broadJson, "publish");
    if (!broadcast->publish || !tempValue) {
        goto BROADCAST_PARSE_ERR;
    }
    tempArrSize = cJSON_GetArraySize(tempValue);
    if (tempArrSize > 0) {
        cJSON *jsonArrItem = NULL;
        for (int i = 0; i < tempArrSize; i++) {
            jsonArrItem = cJSON_GetArrayItem(tempValue, i);
            // LOG_I("publish num: [%d]", tempArrSize);
            if (jsonArrItem) {
                InsertTdlist(broadcast->publish, jsonArrItem->valuestring, strlen(jsonArrItem->valuestring) + 1);
                // LOG_I("publish[%d]: [%s]", i, jsonArrItem->valuestring);
            }
        }
    }
    cJSON_Delete(broadJson);
    return 0;
BROADCAST_PARSE_ERR:
    cJSON_Delete(broadJson);
    return -1;
}

static int8_t unicastMsgParse(const cJSON *unicastJson, NetUnicastPara_t *unicast)
{
    if (unicastJson == NULL || unicast == NULL) {
        LOG_E("NULL POINT! \n");
        return -1;
    }
    cJSON *publishJson = cJSON_GetObjectItem(unicastJson, "publish");
    if (!publishJson) {
        LOG_E("publish is null!");
        return -1;
    }
    strcpy(unicast->publish, cJSON_GetStringValue(publishJson));
    cJSON *params = cJSON_GetObjectItem(unicastJson, "params");
    if (!params) {
        LOG_E("params is null!");
        return -1;
    }
    const char *paramsStr = cJSON_Print(params);
    memset(unicast->params, 0, sizeof(unicast->params));
    strcpy(unicast->params, paramsStr);
    free(paramsStr);
    paramsStr = NULL;

    return 0;
}

int cmpStrDeviceIdFun(const void *data1, const void *data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    const char *para1 = (const char *)data1;
    const NetBroadcastPara_t *para2 = (const NetBroadcastPara_t *)data2;
    return strcmp(para1, para2->id);
}

static int8_t dealBroadcastMsg(const char *broadcastData)
{
    NetBroadcastPara_t *broadcastPara = malloc(sizeof(NetBroadcastPara_t));

    if (!broadcastData || boardcastMsgParse(broadcastData, broadcastPara)) {
        LOG_E("boardcastMsgPrase error!");
        return -1;
    }
    LOG_I("DeviceName:[%s], DeviceId:[%s], type:[%s]", broadcastPara->name, broadcastPara->id, broadcastPara->type);
    if (g_localNetCommCtl.onlineDevList) {
        Node_t *foundNode = FindVdlist(g_localNetCommCtl.onlineDevList, broadcastPara->id, cmpStrDeviceIdFun);
        if (foundNode) {
            LOG_I("find the devInfo from the list!");
            LOG_I("update the DevInfo!");
            free(foundNode->data);
            foundNode->data = broadcastPara;
        } else {
            LOG_I("do not find the devInfo from the list, add the new devInfo to the list!");
            InsertTdlist(g_localNetCommCtl.onlineDevList, broadcastPara, sizeof(NetBroadcastPara_t));
            if (g_localNetCommCtl.devListNoticeCb) {
                g_localNetCommCtl.devListNoticeCb(g_localNetCommCtl.onlineDevList);
            }
        }
    } else {
        LOG_I("g_localNetCommCtl.onlineDevList is null, create it!");
        g_localNetCommCtl.onlineDevList = CreateDlist();
        if (g_localNetCommCtl.onlineDevList) {
            LOG_I("add new node to the list!");
            InsertTdlist(g_localNetCommCtl.onlineDevList, broadcastPara, sizeof(NetBroadcastPara_t));
            if (g_localNetCommCtl.devListNoticeCb) {
                g_localNetCommCtl.devListNoticeCb(g_localNetCommCtl.onlineDevList);
            }
        }
    }
    gettimeofday(&(broadcastPara->time), NULL);
    return 0;
}

static int8_t LocalNetUnicastResponse(const char *pDestDeviceId, const char *pSelfDeviceId, const uint8_t tempId)
{
    int8_t ret = -1;
#if (PRINT_TIME)
    //  for test time
    u32 time1 = getMillionSecond();
#endif
    cJSON *dataJson = cJSON_CreateObject();
    cJSON_AddStringToObject(dataJson, "messageType", RESPONSE);
    cJSON_AddNumberToObject(dataJson, "messageId", tempId);
    cJSON *msgJson = cJSON_CreateObject();
    cJSON_AddStringToObject(msgJson, "id", pSelfDeviceId);
    cJSON_AddStringToObject(msgJson, "result", "OK");
    cJSON_AddNumberToObject(msgJson, "state", 200);
    cJSON_AddItemToObject(dataJson, "message", msgJson);
    char *sendData = cJSON_Print(dataJson);
    cJSON_Delete(dataJson);
    LOG_I("%s", sendData);
    if (sendData != NULL) {
        LocalNetUdpSend(sendData, pDestDeviceId);
        ret = 0;
        free(sendData);
        sendData = NULL;
    }
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif
    return ret;
}

void PRINT_SUBSCRIBE_LIST(Node_t *head)
{
    LOG_I("\r\n");
    if (head == NULL) {
        LOG_E("LIST IS NULL! \n");
        return;
    }
    Node_t *temp = head->after;
    int idx = 0;
    while (temp != head && NULL != temp->data) {
        LOG_I("LIST[%d] = %s \r\n", idx++, temp->data);
        temp = temp->after;
    }
}

static int8_t dealUniCastMsg(const cJSON *jsonTempData, const char *pDeviceId, const uint8_t tempId)
{
#if (PRINT_TIME)
    // for test time
    u32 time1 = getMillionSecond();
#endif

    NetUnicastPara_t singlePublishPara = {0};
    NetBroadcastPara_t *theFoundNetData = NULL;
    if (unicastMsgParse(jsonTempData, &singlePublishPara) < 0) {
        LOG_E("unicastMsgPrase error! \n");
        return -1;
    }
    if (g_localNetCommCtl.onlineDevList == NULL) {
        LOG_E("ERROR! no onlineDevList! \n");
        return -1;
    }

    Node_t *foundNode = FindVdlist(g_localNetCommCtl.onlineDevList, pDeviceId, cmpStrDeviceIdFun);
    if (foundNode) {
        theFoundNetData = (NetBroadcastPara_t *)(foundNode->data);
        // 更新发单播设备时间戳
        gettimeofday(&(theFoundNetData->time), NULL);
    }

    if (g_localNetCommCtl.onlineDevList->after != NULL && g_localNetCommCtl.onlineDevList->after->data != NULL &&
        g_localNetCommCtl.recvCb != NULL) {
        NetBroadcastPara_t *tempNetBroPara = (NetBroadcastPara_t *)(g_localNetCommCtl.onlineDevList->after->data);
        Node_t *foundSubscribeNode = FindVdlist(tempNetBroPara->subscribe, singlePublishPara.publish, cmpStrFun);
        if (foundSubscribeNode) {
            // 使用该回调
            char *msgString = cJSON_Print(jsonTempData);
            // 增加group
            if (theFoundNetData) {
                cJSON *msgJson = cJSON_Parse(msgString);
                free(msgString);
                // 增加group
                cJSON_AddStringToObject(msgJson, "group", theFoundNetData->group);
                msgString = cJSON_Print(msgJson);
                cJSON_Delete(msgJson);
                LOG_I("%s", msgString);
            }

            g_localNetCommCtl.recvCb(msgString);
            free(msgString);
            msgString = NULL;
        } else {
            LOG_E("foundSubscribeNode failed!! publish : %s \n", singlePublishPara.publish);
        }
        LocalNetUnicastResponse(pDeviceId, tempNetBroPara->id, tempId);
    }
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif
    return 0;
}

static void SendMsgListNodePrintFun(const void *data)
{
    LocalNetMsgSendNode *pMsgSendNode = (LocalNetMsgSendNode *)data;
    if (NULL == pMsgSendNode) {
        LOG_E("node->data is null");
        return;
    }

    DeviceIdHang *pDevIdHangNode = pMsgSendNode->pDestDevId;
    LOG_I("##------------------ satrt ---------------------##");
    LOG_I("msgId : %d", pMsgSendNode->msgId);
    LOG_I("msgCnt : %d", pMsgSendNode->sendCnt);
    LOG_I("msgTime : %d", pMsgSendNode->time.tv_sec);
    LOG_I("publish : %s", pMsgSendNode->publish);
    LOG_I("msgDestDevId : ");
    while (pDevIdHangNode) {
        LOG_I("\t%s", pDevIdHangNode->destDevId);
        pDevIdHangNode = pDevIdHangNode->next;
    }
    LOG_I("msg : %s", pMsgSendNode->msg);
    LOG_I("##------------------- end ----------------------##");

    return;
}

static void OnlineDevListNodePrintFun(const void *data)
{
    NetBroadcastPara_t *pOnlineDevNode = (NetBroadcastPara_t *)data;
    if (NULL == pOnlineDevNode) {
        LOG_E("node->data is null");
        return;
    }

    LOG_I("##------------------ satrt ---------------------##");
    LOG_I("devName : %s", pOnlineDevNode->name);
    LOG_I("devType : %s", pOnlineDevNode->type);
    LOG_I("devGroup : %s", pOnlineDevNode->group);
    LOG_I("devId : %s", pOnlineDevNode->id);
    LOG_I("##------------------- end ----------------------##");

    return;
}

static int8_t dealResponseMsg(const cJSON *jsonTempData, const uint8_t tempId)
{
    ResponsePara_t responsePara;
    if (responseMsgPrase(jsonTempData, &responsePara) < 0) {
        LOG_E("responseParaPrase error!");
        return -1;
    }
    Node_t *tempNetBroPara = g_localNetCommCtl.onlineDevList;
    NetBroadcastPara_t *foundResonseNode =
        (NetBroadcastPara_t *)FindVdlist(tempNetBroPara, responsePara.id, cmpStrDeviceIdFun);
    if (foundResonseNode) {
        gettimeofday(&(foundResonseNode->time), NULL);
    }

    // 根据msg id删除对应的事件 tempId
    LocalNetMsgRespData localNetMsgRespData;
    localNetMsgRespData.msgId = tempId;
    strncpy(localNetMsgRespData.deviceId, responsePara.id, DEVICE_ID_LEN);
    // Printdlist(g_localNetCommCtl.sendReadyMsgList->list, SendMsgListNodePrintFun);
    LocalNetMsgSendListDeletebyResp(g_localNetCommCtl.sendReadyMsgList, &localNetMsgRespData);

    return 0;
}

#ifdef L0_DEVICE
void LocalNetCommunicationCtl(void *arg)
#elif defined(L2_DEVICE)
void *LocalNetCommunicationCtl(void *arg)
#endif
{
#ifdef L0_DEVICE
    UNUSED(arg);
#endif
    cJSON *jsonRoot = NULL;
    cJSON *jsonTempType = NULL;
    cJSON *jsonTempId = NULL;
    cJSON *jsonTempData = NULL;
    LocalNetMsgRecv *pMsgRecv = NULL;
    g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_RUNNING;

    while (LOCAL_NET_THREAD_RUNNING == g_localNetCommCtl.recvMsgDealThreadStatus) {
#if (PRINT_TIME)
        // for test time
        u32 time1 = getMillionSecond();
#endif
        // recv queue
#ifdef L0_DEVICE
        int32_t res = osMessageQueueGet(g_localNetCommCtl.recvMsgDealQueue, &pMsgRecv, 0, 0);
        if (osOK != res) {
            // LOG_I("mqueue recv data failed!");
            osDelay(Time2Tick(300));
            continue;
        }
#elif defined(L2_DEVICE)
        pMsgRecv = (LocalNetMsgRecv *)malloc(sizeof(LocalNetMsgRecv));
        if (!pMsgRecv) {
            usleep(300000);
            continue;
        }
        pMsgRecv->dataType = 0;
        if (msgrcv(g_localNetCommCtl.recvMsgDealQueue, pMsgRecv, sizeof(LocalNetMsgRecv), pMsgRecv->dataType, 0) < 0) {
            addLogs("LocalNetCommunicationCtl mqueue recv data failed!");
            free(pMsgRecv);
            pMsgRecv = NULL;
            {
                char errmsg[128] = {0};
                sprintf(errmsg, "%d[%s]", errno, strerror(errno));
                addLogs((const char *)errmsg);
            }
            usleep(300000);
            continue;
        }
#if (PRINT_TIME)
        // for test time
        {
            char tmp[32] = {0};
            sprintf("recv cost time : %d(ms)", (int)(getMillionSecond() - time1));
            addLogs(tmp);
            time1 = getMillionSecond();
        }
#endif
#endif
        // parse msg
        jsonRoot = cJSON_Parse((char *)(pMsgRecv->data));
        if (jsonRoot == NULL) {
            LOG_E("msg json parse failed!");
            free(pMsgRecv);
            pMsgRecv = NULL;
            continue;
        }

        jsonTempType = cJSON_GetObjectItem(jsonRoot, "messageType"); // msg type
        if (jsonTempType == NULL) {
            cJSON_Delete(jsonRoot);
            free(pMsgRecv);
            pMsgRecv = NULL;
            LOG_E("cJSON_GetObjectItem messageType failed! \n");
            continue;
        }
        jsonTempId = cJSON_GetObjectItem(jsonRoot, "messageId"); // msg Id
        if (jsonTempId == NULL) {
            LOG_I("This meaasge have no messageId, Maybe a broadcast!");
        }
        jsonTempData = cJSON_GetObjectItem(jsonRoot, "message"); // msg
        if (jsonTempData == NULL) {
            cJSON_Delete(jsonRoot);
            free(pMsgRecv);
            pMsgRecv = NULL;
            LOG_E("cJSON_GetObjectItem message failed! \n");
            continue;
        }
        const char *pMsgeData = cJSON_Print(jsonTempData);
        if (!strcmp(jsonTempType->valuestring, BROADCAST)) { // 广播
            dealBroadcastMsg(pMsgeData);
        } else if (!strcmp(jsonTempType->valuestring, UNICAST)) { // 单播
            dealUniCastMsg(jsonTempData, pMsgRecv->deviceId, jsonTempId->valueint);
        } else if (!strcmp(jsonTempType->valuestring, RESPONSE)) { // 回复
            dealResponseMsg(jsonTempData, jsonTempId->valueint);
        }
        cJSON_Delete(jsonRoot);
        free(pMsgeData);
        pMsgeData = NULL;
        free(pMsgRecv);
        pMsgRecv = NULL;

// for test time
#if (PRINT_TIME)
        {
            char tmp[32] = {0};
            sprintf("%s cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
            addLogs(tmp);
        }
#endif
    }

    if (LOCAL_NET_THREAD_RELEASE == g_localNetCommCtl.recvMsgDealThreadStatus) {
        g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_EXIT;
    } else {
        g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_ERR;
        LOG_E("recvMsgDealThread release error!");
    }

#ifdef L0_DEVICE
    return;
#elif defined(L2_DEVICE)
    return NULL;
#endif
}

#ifdef L0_DEVICE
void LocalNetMsgSendDeal(void *arg)
#elif defined(L2_DEVICE)
void *LocalNetMsgSendDeal(void *arg)
#endif
{
#ifdef L0_DEVICE
    UNUSED(arg);
#endif
    char *sendMsg = NULL;
    struct timeval curTimeval;
    DeviceIdHang *pDeviceIdHang = NULL;
    LocalNetMsgSendNode *pMsgSendNode = NULL;
    memset(&curTimeval, 0, sizeof(struct timeval));
    while (1) {
#if (PRINT_TIME)
        // for test time
        u32 time1 = getMillionSecond();
#endif
        gettimeofday(&curTimeval, NULL);
        pMsgSendNode = LocalNetMsgSendListNodeGet(g_localNetCommCtl.sendReadyMsgList);
        if (pMsgSendNode == NULL ||
            (5 > pMsgSendNode->sendCnt) && (5 > (curTimeval.tv_sec - pMsgSendNode->time.tv_sec))) {
#ifdef L0_DEVICE
            // LOG_I("no msg need to send.");
            osDelay(Time2Tick(300));
#elif defined(L2_DEVICE)
            usleep(300000);
#endif
            continue;
        }

        LOG_I("sendMsgCnt : %d,", pMsgSendNode->sendCnt);
        LOG_I("send MsgId : %d,", pMsgSendNode->msgId);
        LOG_I("send msg : %s,", pMsgSendNode->msg);
        LOG_I("last send time : %d,", pMsgSendNode->time.tv_sec);
        LOG_I("current time : %d.", curTimeval.tv_sec);

        // 制作发送数据
        cJSON *msg = cJSON_CreateObject();
        cJSON_AddStringToObject(msg, "messageType", UNICAST);
        cJSON_AddNumberToObject(msg, "messageId", pMsgSendNode->msgId);
        cJSON *msgBody = cJSON_Parse(pMsgSendNode->msg);
        cJSON_AddItemToObject(msg, "message", msgBody);
        sendMsg = cJSON_Print(msg);
        pDeviceIdHang = pMsgSendNode->pDestDevId;

        while (pDeviceIdHang) {
#if (PRINT_TIME)
            u32 time2 = getMillionSecond();
#endif

            LocalNetUdpSend(sendMsg, pDeviceIdHang->destDevId);
            pDeviceIdHang = pDeviceIdHang->next;

// for test time
#if (PRINT_TIME)
            {
                char tmp[32] = {0};
                sprintf("%s pDeviceIdHang loop cost time : %d(ms)", __func__, (int)(getMillionSecond() - time2));
                addLogs(tmp);
            }
#endif
        }
        pMsgSendNode->time.tv_sec = curTimeval.tv_sec;
        pMsgSendNode->sendCnt--;
        if (!(pMsgSendNode->sendCnt)) { // 重发已到最大次数
            LocalNetMsgSendListNodeDelete(g_localNetCommCtl.sendReadyMsgList, pMsgSendNode->msgId);
        }
        free(sendMsg);
        sendMsg = NULL;
        cJSON_Delete(msg);
#if (PRINT_TIME)
        // for test time
        {
            char tmp[32] = {0};
            sprintf("%s  one loop cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
            addLogs(tmp);
        }
#endif
    }
}

/**
* @brief 广播发送的设备信息+订阅、发布信息
*
{
    "device":{
        "name":"RK3568 parking background management system"
        "type" : "parkingSystem",
        "id" : "97234126",
        "priority": 250，
        "group" : "all",
    }，
    "subscribe" : [
    "carApproachDetect"，"licensePlateRecognition","latchChange"
    ],
    "publish" : ["latchControl"]
}
*/
static int8_t LocalNetDevInfoMake(char *broadcastBuf, void *data)
{
    if (!broadcastBuf || !data) {
        return -1;
    }
    NetBroadcastPara_t *tempNetBroPara = (NetBroadcastPara_t *)data;
    char *pBroadCastMsg = NULL;
    cJSON *broadCastJson = cJSON_CreateObject();
    cJSON_AddStringToObject(broadCastJson, "messageType", BROADCAST);
    cJSON *messageJson = cJSON_CreateObject();
    cJSON *deviceJson = cJSON_AddObjectToObject(messageJson, "device");
    cJSON_AddStringToObject(deviceJson, "name", tempNetBroPara->name);
    cJSON_AddStringToObject(deviceJson, "type", tempNetBroPara->type);
    char mac[32] = {};
#ifdef L0_DEVICE
    const char *netDeviceName = "wlan0";
#elif defined(L2_DEVICE)
    const char *netDeviceName = "eth0"; // L2设备插网线时候是："eth0", 使用wifi时候：“wlan0”;
#endif
    int getmacret = getLocalMacAddr(netDeviceName, mac, 32);
    if (getmacret >= 0) {
        char idArr[512] = {};
        sprintf(idArr, "%s_%s_%s", tempNetBroPara->type, tempNetBroPara->group, mac);
        LOG_I("%s", idArr);
        char sha256ID[256] = {};
        StrSha256(idArr, strlen(idArr), sha256ID);
        cJSON_AddStringToObject(deviceJson, "id", sha256ID);
        bzero(tempNetBroPara->id, sizeof(tempNetBroPara->id));
        sprintf(tempNetBroPara->id, "%s", sha256ID);
        cJSON_AddNumberToObject(deviceJson, "priority", tempNetBroPara->priority);
        cJSON_AddStringToObject(deviceJson, "group", tempNetBroPara->group);
        // subscribe
        cJSON *subscribe = cJSON_AddArrayToObject(messageJson, "subscribe");
        if (tempNetBroPara->subscribe && tempNetBroPara->subscribe->after) {
            Node_t *tmp_subscribe = tempNetBroPara->subscribe->after;
            while (tmp_subscribe != tempNetBroPara->subscribe) {
                char *tmpSubContent = tmp_subscribe->data;
                cJSON *tmpSubJsonItem = cJSON_CreateString(tmpSubContent);
                cJSON_AddItemToArray(subscribe, tmpSubJsonItem);
                tmp_subscribe = tmp_subscribe->after;
            }
        }
        // publish
        cJSON *publish = cJSON_AddArrayToObject(messageJson, "publish");
        if (tempNetBroPara->publish && tempNetBroPara->publish->after) {
            Node_t *tmp_publish = tempNetBroPara->publish->after;
            while (tmp_publish != tempNetBroPara->publish) {
                char *tmpPubContent = tmp_publish->data;
                cJSON *tmpPubJsonItem = cJSON_CreateString(tmpPubContent);
                cJSON_AddItemToArray(publish, tmpPubJsonItem);
                tmp_publish = tmp_publish->after;
            }
        }
        cJSON_AddItemToObject(broadCastJson, "message", messageJson);
        pBroadCastMsg = cJSON_Print(broadCastJson);
        // sendBroadCastBuf
        bzero(broadcastBuf, BROADCAST_ARRSIZE);
        snprintf(broadcastBuf, strlen(pBroadCastMsg) + 1, "%s", pBroadCastMsg);
        cJSON_Delete(broadCastJson);
        free(pBroadCastMsg);
        pBroadCastMsg = NULL;
    }

    return 0;
}

int8_t LocalNetDevAttributeBoardCast(void)
{
    int8_t ret = -1;
    time_t t;
    /* 初始化随机数发生器 */
    srand((unsigned)time(&t));
    // 开线程、发广播
    if (g_localNetCommCtl.onlineDevList && g_localNetCommCtl.onlineDevList->after->data) {
        char broadcastBuf[BROADCAST_ARRSIZE] = {0};
        // 创建广播报文
        LocalNetDevInfoMake(broadcastBuf, g_localNetCommCtl.onlineDevList->after->data);
        // 开启线程
        if (!LocalNetUdpBoardcast(broadcastBuf, 8 + rand() % 8)) {
            ret = 0;
        }
    }
    return ret;
}

#ifdef L0_DEVICE
static void LocalNetDevOfflineJudge(void *arg)
#elif defined(L2_DEVICE)
static void *LocalNetDevOfflineJudge(void *arg)
#endif
{
    struct timeval curTimeval;
    g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_RUNNING;
    while (LOCAL_NET_THREAD_RUNNING == g_localNetCommCtl.devOfflineJudgeThreadStatus) {
        if (g_localNetCommCtl.onlineDevList) {
            // 循环 netOnlineDeviceDList 查找订阅
            Node_t *tmpNetOnlineDeviceDList = g_localNetCommCtl.onlineDevList->after;
            NetBroadcastPara_t *tempNetBroPara = (NetBroadcastPara_t *)tmpNetOnlineDeviceDList->data;
            while (tempNetBroPara && tmpNetOnlineDeviceDList != g_localNetCommCtl.onlineDevList) {
                gettimeofday(&curTimeval, NULL);
                DeviceNetState hisState = tempNetBroPara->state;
                if (curTimeval.tv_sec - tempNetBroPara->time.tv_sec >= 40) {
                    tempNetBroPara->state = LOCAL_NET_OFFLINE;
                    if ((g_localNetCommCtl.devListNoticeCb) && hisState == LOCAL_NET_ONLINE) {
                        g_localNetCommCtl.devListNoticeCb(g_localNetCommCtl.onlineDevList);
                    }
                } else {
                    tempNetBroPara->state = LOCAL_NET_ONLINE;
                    if ((g_localNetCommCtl.devListNoticeCb) && hisState == LOCAL_NET_OFFLINE) {
                        g_localNetCommCtl.devListNoticeCb(g_localNetCommCtl.onlineDevList);
                    }
                }
                tmpNetOnlineDeviceDList = tmpNetOnlineDeviceDList->after;
                tempNetBroPara = (NetBroadcastPara_t *)tmpNetOnlineDeviceDList->data;
            }
        }
#ifdef L0_DEVICE
        osDelay(10 * 1000);
#elif defined(L2_DEVICE)
        usleep(10000000);
#endif
    }
    if (LOCAL_NET_THREAD_RELEASE == g_localNetCommCtl.devOfflineJudgeThreadStatus) {
        g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_EXIT;
    } else {
        g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_ERR;
        LOG_E("devOfflineJudgeThread release error!");
    }

#ifdef L0_DEVICE
    return;
#elif defined(L2_DEVICE)
    return NULL;
#endif
}

static uint8_t LocalNetGetNetStatus(void)
{
    int8_t ret = -1;

#ifdef L0_DEVICE
    if (0 < BOARD_GetWifiSignalLevel()) {
        ret = 0;
    }
#elif defined(L2_DEVICE)
    char mac[32] = {};
    const char *netDeviceName = "eth0"; // L2设备插网线时候是："eth0", 使用wifi时候：“wlan0”;
    int getmacret = getLocalMacAddr(netDeviceName, mac, 32);
    if (getmacret >= 0) {
        ret = 0;
    }
#endif

    return ret;
}

static DeviceIdHang *LocalNetOnlineDevSubscribeGet(DestDevIdCheckData *pDestDevIdCheckData)
{
    DeviceIdHang *pDevIdHangNext = NULL;
    DeviceIdHang *pDevIdHangNode = NULL;
    NetBroadcastPara_t *pOnlineDevInfo = NULL;

    Node_t *node = g_localNetCommCtl.onlineDevList->after;
    if (!node) {
        LOG_E("onlineDevList is NULL!");
        return NULL;
    }
    LOG_I("self publish -> [%s]", pDestDevIdCheckData->subscribe);

    Node_t *firstNode = FindVdlist(node, pDestDevIdCheckData, DestDevIdCheckDataCmp);
    if (!firstNode) {
        LOG_I("no member subscribe this publish on the list!");
        return NULL;
    }
    node = firstNode;
    // 为找到的devId申请内存
    pDevIdHangNode = malloc(sizeof(DeviceIdHang));
    if (!pDevIdHangNode) {
        LOG_E("malloc pDevIdHangNode failed!");
        return NULL;
    }
    memset(pDevIdHangNode, 0, sizeof(DeviceIdHang));
    // 将找到的节点按照设备信息的格式整理
    pDevIdHangNode->next = NULL;
    pOnlineDevInfo = (NetBroadcastPara_t *)(node->data);
    strcpy(pDevIdHangNode->destDevId, pOnlineDevInfo->id);
    while (1) {
        pDevIdHangNext = pDevIdHangNode;
        node = FindVdlist(node, pDestDevIdCheckData, DestDevIdCheckDataCmp);
        if ((!node) || (firstNode == node)) { // 不存在订阅该publish的成员
            LOG_I("have search all member of the list!");
            break;
        }
        // 为找到的devId申请内存
        pDevIdHangNode = malloc(sizeof(DeviceIdHang));
        if (!pDevIdHangNode) {
            LOG_E("malloc pDevIdHangNode failed!");
            while (pDevIdHangNode) {
                pDevIdHangNext = pDevIdHangNode->next;
                free(pDevIdHangNode);
                pDevIdHangNode = pDevIdHangNext;
            }
            return NULL;
        }
        memset(pDevIdHangNode, 0, sizeof(DeviceIdHang));
        pDevIdHangNode->next = pDevIdHangNext;
        // 将找到的节点按照设备信息的格式整理
        pOnlineDevInfo = (NetBroadcastPara_t *)node->data;
        strcpy(pDevIdHangNode->destDevId, pOnlineDevInfo->id);
    }

    return pDevIdHangNode;
}

static int8_t publishCheck(const char *publish)
{
    int8_t ret = -1;
    NetBroadcastPara_t *selfDevInfo = NULL;
    NetBroadcastPara_t *samePublishDevInfo = NULL;

    if (g_localNetCommCtl.onlineDevList == NULL) {
        LOG_E("LocalNet maybe not init now, please call LocalNetInit first!");
        return ret;
    }
    selfDevInfo = (NetBroadcastPara_t *)g_localNetCommCtl.onlineDevList->after->data;

    Node_t *node = g_localNetCommCtl.onlineDevList->after;
    if (!node) {
        LOG_E("onlineDevList is NULL!");
        return ret;
    }
    Node_t *firstNode = FindVdlist(node, publish, PublishCmp);
    if (!firstNode) {
        LOG_E("no member have this publish on the list!");
        ret = 0;
        return ret;
    }
    node = firstNode;
    while (1) {
        samePublishDevInfo = node->data;
        if (samePublishDevInfo && (samePublishDevInfo->priority > selfDevInfo->priority)) {
            LOG_I("have online device priority higher than self device.");
            break;
        }
        node = FindVdlist(node, publish, PublishCmp);
        if ((!node) || (firstNode == node)) {
            LOG_I("have search all member of the list!");
            ret = 0;
            break;
        }
    }
    return ret;
}

int8_t LocalNetMsgSend(const char *publish, const char *params)
{
    int8_t ret = -1;
    char *sendMsg = NULL;
    cJSON *msg = NULL;
    LocalNetMsgSendNode msgSendNode;
    DestDevIdCheckData destDevIdCheckData;
    // 判断当前publish是否有更高级的设备
    if (publishCheck(publish)) {
        LOG_E("can not publish this commond!");
        return ret;
    }

    // 制作发送数据
    msg = cJSON_CreateObject();
    cJSON_AddStringToObject(msg, "publish", publish);
    cJSON *paramsJson = cJSON_Parse(params);
    memset(&destDevIdCheckData, 0, sizeof(destDevIdCheckData));
    cJSON *groupJson = cJSON_GetObjectItem(paramsJson, "group"); // msg type
    if (groupJson != NULL) {
        LOG_I("msg have group, is L2 device!");
        strncpy(destDevIdCheckData.group, groupJson->valuestring, 32);
    } else {
        NetBroadcastPara_t *pNetBoardcastData = g_localNetCommCtl.onlineDevList->after->data;
        if (pNetBoardcastData) {
            LOG_I("copy self group! to send msg");
            strncpy(destDevIdCheckData.group, pNetBoardcastData->group, 32);
        }
    }
    strncpy(destDevIdCheckData.subscribe, publish, strlen(publish) + 1);
    cJSON_AddItemToObject(msg, "params", paramsJson);
    sendMsg = cJSON_Print(msg);
    if (!sendMsg) {
        return ret;
    }
    // 初始化发送信息节点
    memset(&msgSendNode, 0, sizeof(LocalNetMsgSendNode));
    // 获取发送目标
    msgSendNode.pDestDevId = LocalNetOnlineDevSubscribeGet(&destDevIdCheckData);
    if (!msgSendNode.pDestDevId) {
        free(sendMsg);
        sendMsg = NULL;
        cJSON_Delete(msg);
        return ret;
    }
    msgSendNode.msg = sendMsg;

    strncpy(msgSendNode.publish, publish, strlen(publish) + 1);
    LocalNetMsgSendListNodeDeleteByPublish(g_localNetCommCtl.sendReadyMsgList, publish);
    if (-1 == LocalNetMsgSendListNodeAdd(g_localNetCommCtl.sendReadyMsgList, &msgSendNode)) {
        free(sendMsg);
        sendMsg = NULL;
        cJSON_Delete(msg);
        return ret;
    }
    Printdlist(g_localNetCommCtl.sendReadyMsgList->list, SendMsgListNodePrintFun);
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif

    cJSON_Delete(msg);
    ret = 0;
    return ret;
}

int8_t LocalNetSelfInfoSet(NetBroadcastPara_t *selfInfo)
{
    int8_t ret = -1;
    g_localNetCommCtl.onlineDevList = CreateDlist();
    if (g_localNetCommCtl.onlineDevList) {
        InsertHdlist(g_localNetCommCtl.onlineDevList, selfInfo, sizeof(NetBroadcastPara_t));
        ret = 0;
    }
    return ret;
}

static int8_t UdpRecvCb(const char *pMsg, const char *pDeviceId)
{
    int8_t ret = -1;
    uint16_t msgLen = 0;
    msgLen = strlen(pMsg);

#if (PRINT_TIME)
    // test for time
    u32 time1 = getMillionSecond();
#endif

    LocalNetMsgRecv *pRecvMsg = (LocalNetMsgRecv *)malloc(sizeof(LocalNetMsgRecv));
    if (!pRecvMsg) {
        LOG_E("pRecvMsg malloc failed!");
        goto UDP_RECV_CB_ERR;
    }
    memset(pRecvMsg, 0, sizeof(LocalNetMsgRecv));

    pRecvMsg->dataLen = msgLen + 1;
    strncpy(pRecvMsg->deviceId, pDeviceId, DEVICE_ID_LEN);
    strncpy(pRecvMsg->data, pMsg, msgLen + 1);

    // udpSendData send queue
#ifdef L0_DEVICE
    if (osOK != osMessageQueuePut(g_localNetCommCtl.recvMsgDealQueue, &pRecvMsg, 0, 0)) {
        LOG_E("osMessageQueuePut error.");
        goto UDP_RECV_CB_ERR;
    }
#elif defined(L2_DEVICE)
    pRecvMsg->dataType = 0;
    if (msgsnd(g_localNetCommCtl.recvMsgDealQueue, pRecvMsg, sizeof(LocalNetMsgRecv), 0) < 0) { //
        addLogs("LocalNetCommunicationCtl mqueue send data failed!");
        LOG_E("osMessageQueuePut error.");
        {
            char errmsg[128] = {0};
            sprintf(errmsg, "msg send err : %d[%s]", errno, strerror(errno));
            addLogs((const char *)errmsg);
        }
        goto UDP_RECV_CB_ERR;
    }
    free(pRecvMsg);
    pRecvMsg = NULL;
#endif
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s success cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif
    ret = 0;
    return ret;

UDP_RECV_CB_ERR:
    if (pRecvMsg) {
        free(pRecvMsg);
        pRecvMsg = NULL;
    }
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s failed cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif
    return ret;
}

int8_t LocalNetInit(void)
{
    int8_t ret = -1;
    if (LocalNetGetNetStatus()) {
        LOG_E("net is not connected!");
        return ret;
    }

    LocalNetUdpRecvCbReg(UdpRecvCb);

    if (LocalNetUdpInit()) {
        LOG_E("UDP init failed!");
        return ret;
    }

    if (LocalNetDevAttributeBoardCast()) {
        LOG_E("boardcast start failed!");
        return ret;
    }

#ifdef L0_DEVICE
    // create udp send msg queue.
    g_localNetCommCtl.recvMsgDealQueue =
        osMessageQueueNew(MQ_MSG_NUM_MAX, MQ_MSG_SIZE_MAX, (osMessageQueueAttr_t *)NULL);
    if (NULL == g_localNetCommCtl.recvMsgDealQueue) {
        LOG_E("osMessageQueueNew faild!");
        return ret;
    }
#elif defined(L2_DEVICE)
    // 获取key
    if ((g_localNetCommCtl.key = ftok("./", 0xa)) < 0) {
        LOG_E("osMessageQueueNew faild!");
        return ret;
    }

    g_localNetCommCtl.key = 0;
    g_localNetCommCtl.recvMsgDealQueue = msgget(g_localNetCommCtl.key, IPC_CREAT | 0666);
    if (g_localNetCommCtl.recvMsgDealQueue < 0) {
        LOG_E("osMessageQueueNew faild!");
        return ret;
    }
#endif
    g_localNetCommCtl.sendReadyMsgList = LocalNetMsgSendListInit();
    if (NULL == g_localNetCommCtl.sendReadyMsgList) {
        LOG_E("msgSendList init faild!");
        return ret;
    }
    g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_INIT;
    g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_INIT;
    g_localNetCommCtl.sendMsgDealThreadStatus = LOCAL_NET_THREAD_INIT;
#ifdef L0_DEVICE
    osThreadAttr_t attr;
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.name = "OfflineJudge";
    attr.stack_size = 1024 * 4;
    attr.priority = 24;

    if ((g_localNetCommCtl.devOfflineJudgeThread = osThreadNew((osThreadFunc_t)LocalNetDevOfflineJudge, NULL, &attr)) ==
	    NULL) {
        LOG_E("Could not create the recvMsgDeal thread.");
        return ret;
    }

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.name = "CommCtl";
    attr.stack_size = 1024 * 4;
    attr.priority = 24;
    if ((g_localNetCommCtl.recvMsgDealThread = osThreadNew((osThreadFunc_t)LocalNetCommunicationCtl, NULL, &attr)) ==
        NULL) {
        LOG_E("Could not create the recvMsgDeal thread.");
        return ret;
    }
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.name = "MsgSendDeal";
    attr.stack_size = 1024 * 4;
    attr.priority = 24;
    if ((g_localNetCommCtl.sendMsgDealThread = osThreadNew((osThreadFunc_t)LocalNetMsgSendDeal, NULL, &attr)) == NULL) {
        LOG_E("Could not create the MsgSendDeal thread.");
        return ret;
    }
#elif defined(L2_DEVICE)
    // 开线程，检查设备是否掉线
    if (pthread_create(&(g_localNetCommCtl.devOfflineJudgeThread), NULL, LocalNetDevOfflineJudge, NULL) != EXEC_SUCC) {
        LOG_E("Could not create the LocalNetDevOfflineJudge thread.");
        return ret;
    }
    pthread_detach(g_localNetCommCtl.devOfflineJudgeThread);

    // 开线程，接收其他设备发送的信息
    if (pthread_create(&(g_localNetCommCtl.recvMsgDealThread), NULL, LocalNetCommunicationCtl, NULL) != EXEC_SUCC) {
        LOG_E("Could not create the LocalNetCommunicationCtl thread.");
        return ret;
    }
    pthread_detach(g_localNetCommCtl.recvMsgDealThread);

    // 开线程，信息发送的处理
    if (pthread_create(&(g_localNetCommCtl.sendMsgDealThread), NULL, LocalNetMsgSendDeal, NULL) != EXEC_SUCC) {
        LOG_E("Could not create the LocalNetMsgSendDeal thread.");
        return ret;
    }
    pthread_detach(g_localNetCommCtl.sendMsgDealThread);
#endif

    ret = 0;
    return ret;
}

int8_t LocalNetDeinit(void)
{
    g_localNetCommCtl.sendMsgDealThreadStatus = LOCAL_NET_THREAD_RELEASE;
    g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_RELEASE;
    g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_RELEASE;

    LocalNetmsgSendListDeinit(g_localNetCommCtl.sendReadyMsgList);

    return 0;
}

Node_t *getOnlineDevList()
{
    return g_localNetCommCtl.onlineDevList;
}
